﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using COFE.Core;
using COFE.Data.Profile;
using NUnit.Framework;

namespace COFE.Data
{
    public class DBUserProfile : UserProfile, IUserProfile2
    {
        #region Constructor


        private DBUserProfile(COFE.Data.User user)
            : base(user.UserId, up => new DBVolumeManager(up))
        {
            Assert.IsNotNull(user);

            AuthorizationKey = user.AuthorizeKey;
            AuthorizationExpireTimeUtc = user.LoginTime.Add(COFEDBShared.TTLUserExpire);            

            EntryListManager = new DBEntryListManager(this);
        }

        public static bool Remove(string userName)
        {
            userName = userName.ToLower();

            return COFEDBShared.DBOperations.UpdateDatabase((context) =>
            {
                var user = (from u in context.Users
                            where u.UserId == userName
                            select u).FirstOrDefault();

                if (user == null)
                    return false;

                context.Users.DeleteObject(user);

                context.SaveChanges();
                return true;
            });
        }

        public static bool Exists(string userName)
        {
            userName = userName.ToLower();

            return COFEDBShared.DBOperations.ReadDatabase((context) =>
            {
                return context.Users.Any(u => u.UserId == userName);
            });
        }

        
        public static IUserProfile2 Create(string userName, string password)
        {
            userName = userName.ToLower();

            DBUserProfile newUserProfile = null;

            COFEDBShared.DBOperations.UpdateDatabase((context) =>
             {
                 if (context.UserExists(userName))
                     throw new ArgumentException("User already exists.");

                 newUserProfile = new DBUserProfile(context.CreateUser(userName, password));                                 
             });

            return newUserProfile;
        }

        public static void Delete(string userName)
        {
            COFEDBShared.DBOperations.UpdateDatabase((context) =>
            {
                var user = context.LookupUser(userName);
                if (user == null) return;

                context.Users.DeleteObject(user);
                context.SaveChanges();
            });

        
        }

        public static IUserProfile2 GetUserProfile(string userName, string password)
        {
            userName = userName.ToLower();

            DBUserProfile newUserProfile = null;
            return COFEDBShared.DBOperations.UpdateDatabase((context) =>
            {             
                var user = context.LookupUser(userName, password);
                if (user == null) throw new KeyNotFoundException("User not found.");
                user.Permissions.Load();

                context.RefreshUser(user, true);
                context.SaveChanges();
                newUserProfile = new DBUserProfile(user);
                
                return newUserProfile;
            });
        }
       

        public static IUserProfile2 GetUserProfile(Guid authorizationKey)
        {
            return COFEDBShared.DBOperations.UpdateDatabase((context) =>
            {
                var user = context.LookupUser(authorizationKey);
                if (user == null) throw new KeyNotFoundException("User not found.");

                user.Permissions.Load();
                context.RefreshUser(user, true);
                context.SaveChanges();

                var newUserProfile = new DBUserProfile(user);                
                return newUserProfile;
            });
        }

        public static IUserProfile2 Login(string userName, string password)
        {
            var retVal = GetUserProfile(userName, password);
            COFEShared.UserProfileManager.SetCurrentUserProfile(retVal);
            return retVal;
        }

        public static IUserProfile2 Login(Guid authorizationKey)
        {
            var retVal = GetUserProfile(authorizationKey);
            COFEShared.UserProfileManager.SetCurrentUserProfile(retVal);
            return retVal;
        }

        public static void Logout(Guid authorizationKey)
        {
            COFEDBShared.DBOperations.ReadDatabase((context) =>
            {
                var user = context.LookupUser(authorizationKey);
                if (user == null) return;

                user.LoginTime = COFEDBShared.DTMin;
                context.SaveChanges();
            });
        }

        public static IEnumerable<DBUserProfile> GetAllUserProfiles()
        {
            return COFEDBShared.DBOperations.ReadDatabase((context) =>
                {
                    List<DBUserProfile> retList = new List<DBUserProfile>();
                    foreach (var u in context.Users)
                        retList.Add(new DBUserProfile(u));
                    return retList;
                });            
        }

        #endregion

        #region Public Proerties

        public Guid AuthorizationKey { get; private set; }
        public DateTime AuthorizationExpireTimeUtc { get; set; }

        #endregion
    }
}
